/*
 * Copyright [yyyy] [name of copyright owner]
 * Licensed under the Apache License, Version 2.0 (the "License");
 * You may obtain a copy of the License at

 * http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.github.akashohos90.imageletter.drawable;

import java.util.Locale;

import ohos.agp.colors.RgbColor;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.agp.utils.TextAlignment;

/**
 * Text Drawable
 *
 * @since 2021-05-27
 */
public class TextDrawable extends ShapeElement {
    private static final float SHADE_FACTOR = 0.9f;

    private static final int VALUE_TWO = 2;

    private static final int VALUE_DEFAULT = -1;

    private final Paint mTextPaint;

    private final String mText;

    private final int mColor;

    private final int mShape;

    private final int mHeight;

    private final int mWidth;

    private final int mFontSize;

    private final float mRadius;

    private final int mBorderThickness;

    private final int mBorderColor;

    private TextDrawable(Builder builder) {
        super();

        // shape properties
        mShape = builder.buiShape;
        mHeight = builder.buiHeight;
        mWidth = builder.buiWidth;
        mRadius = builder.buiRadius;

        // text and drawable color
        mText = builder.isUpperCase ? builder.buiText.toUpperCase(Locale.ROOT) : builder.buiText;
        mColor = builder.buiColor;

        // text paint settings
        mFontSize = builder.buiFontSize;
        mTextPaint = new Paint();
        mTextPaint.setColor(new Color(builder.buiTextColor));
        mTextPaint.setAntiAlias(true);
        mTextPaint.setFakeBoldText(builder.isBold);
        mTextPaint.setStyle(Paint.Style.FILL_STYLE);
        mTextPaint.setFont(builder.buiFont);
        mTextPaint.setTextAlign(TextAlignment.CENTER);
        mTextPaint.setStrokeWidth(builder.buiBorderThickness);

        // border settings
        mBorderThickness = builder.buiBorderThickness;
        mBorderColor = builder.buiBorderColor;
    }

    private int getDarkerShade(int color) {
        RgbColor rgb = RgbColor.fromArgbInt(color);
        return Color.rgb((int) (SHADE_FACTOR * rgb.getRed()),
                (int) (SHADE_FACTOR * rgb.getGreen()),
                (int) (SHADE_FACTOR * rgb.getBlue()));
    }

    @Override
    public void drawToCanvas(Canvas canvas) {
        setShape(mShape);
        setCornerRadius(mRadius);
        setStroke(mBorderThickness, RgbColor.fromArgbInt(getDarkerShade(mBorderColor)));
        setRgbColor(RgbColor.fromArgbInt(mColor));
        super.drawToCanvas(canvas);

        // draw text
        Rect rect = getBounds();
        int tempWidth = this.mWidth < 0 ? rect.getWidth() : this.mWidth;
        int tempHeight = this.mHeight < 0 ? rect.getHeight() : this.mHeight;
        int tempFontSize = this.mFontSize < 0 ? (Math.min(tempWidth, tempHeight) / VALUE_TWO) : this.mFontSize;
        mTextPaint.setTextSize(tempFontSize);
        canvas.drawText(mTextPaint, mText, rect.getCenterX(),
                rect.getCenterY() - (((int) mTextPaint.descent() + (int) mTextPaint.ascent()) / VALUE_TWO));
    }

    @Override
    public void setAlpha(int alpha) {
        mTextPaint.setAlpha(alpha);
    }

    /**
     * builder
     *
     * @return IShapeBuilder
     */
    public static IShapeBuilder builder() {
        return new Builder();
    }

    /**
     * Builder
     *
     * @since 2021-05-27
     */
    public static class Builder implements IConfigBuilder, IShapeBuilder, IBuilder {
        private String buiText;

        private int buiColor;

        private int buiBorderThickness;

        private int buiBorderColor;

        private int buiWidth;

        private int buiHeight;

        private Font buiFont;

        private int buiShape;

        private int buiTextColor;

        private int buiFontSize;

        private boolean isBold;

        private boolean isUpperCase;

        private float buiRadius;

        private Builder() {
            buiText = "";
            buiColor = Color.GRAY.getValue();
            buiTextColor = Color.WHITE.getValue();
            buiBorderThickness = 0;
            buiBorderColor = Color.BLACK.getValue();
            buiWidth = VALUE_DEFAULT;
            buiHeight = VALUE_DEFAULT;
            buiShape = ShapeElement.RECTANGLE;
            buiFont = Font.SANS_SERIF;
            buiFontSize = VALUE_DEFAULT;
            isBold = false;
            isUpperCase = false;
        }

        /**
         * width
         *
         * @param width width
         * @return IConfigBuilder
         */
        public IConfigBuilder width(int width) {
            this.buiWidth = width;
            return this;
        }

        /**
         * height
         *
         * @param height height
         * @return IConfigBuilder
         */
        public IConfigBuilder height(int height) {
            this.buiHeight = height;
            return this;
        }

        /**
         * textColor
         *
         * @param color textColor
         * @return IConfigBuilder
         */
        public IConfigBuilder textColor(int color) {
            this.buiTextColor = color;
            return this;
        }

        /**
         * withBorder
         *
         * @param thickness thickness
         * @return IConfigBuilder
         */
        public IConfigBuilder withBorder(int thickness) {
            this.buiBorderThickness = thickness;
            return this;
        }

        /**
         * withBorderColor
         *
         * @param borderColor borderColor
         * @return IConfigBuilder
         */
        public IConfigBuilder withBorderColor(int borderColor) {
            this.buiBorderColor = borderColor;
            return this;
        }

        /**
         * useFont
         *
         * @param font font
         * @return IConfigBuilder
         */
        public IConfigBuilder useFont(Font font) {
            this.buiFont = font;
            return this;
        }

        /**
         * fontSize
         *
         * @param size size
         * @return IConfigBuilder
         */
        public IConfigBuilder fontSize(int size) {
            this.buiFontSize = size;
            return this;
        }

        /**
         * bold
         *
         * @return IConfigBuilder
         */
        public IConfigBuilder bold() {
            this.isBold = true;
            return this;
        }

        /**
         * toUpperCase
         *
         * @return this
         */
        public IConfigBuilder toUpperCase() {
            this.isUpperCase = true;
            return this;
        }

        @Override
        public IConfigBuilder beginConfig() {
            return this;
        }

        @Override
        public IShapeBuilder endConfig() {
            return this;
        }

        @Override
        public IBuilder rect() {
            this.buiShape = ShapeElement.RECTANGLE;
            return this;
        }

        @Override
        public IBuilder round() {
            this.buiShape = ShapeElement.OVAL;
            return this;
        }

        @Override
        public IBuilder roundRect(int radius) {
            this.buiRadius = radius;
            this.buiShape = ShapeElement.RECTANGLE;

            return this;
        }

        @Override
        public TextDrawable buildRect(String text, int color) {
            rect();
            return build(text, color);
        }

        @Override
        public TextDrawable buildRoundRect(String text, int color, int radius) {
            roundRect(radius);
            return build(text, color);
        }

        @Override
        public TextDrawable buildRound(String text, int color) {
            round();
            return build(text, color);
        }

        @Override
        public TextDrawable build(String text, int color) {
            this.buiColor = color;
            this.buiText = text;
            return new TextDrawable(this);
        }
    }

    /**
     * IConfigBuilder Interface
     *
     * @since 2021-05-27
     */
    public interface IConfigBuilder {
        /**
         * width
         *
         * @param width width
         * @return IConfigBuilder
         */
        IConfigBuilder width(int width);

        /**
         * height
         *
         * @param height
         * @return IConfigBuilder
         */
        IConfigBuilder height(int height);

        /**
         * textColor
         *
         * @param color color
         * @return IConfigBuilder
         */
        IConfigBuilder textColor(int color);

        /**
         * withBorder
         *
         * @param thickness thickness
         * @return IConfigBuilder
         */
        IConfigBuilder withBorder(int thickness);

        /**
         * withBorderColor
         *
         * @param color color
         * @return IConfigBuilder
         */
        IConfigBuilder withBorderColor(int color);

        /**
         * useFont
         *
         * @param font font
         * @return IConfigBuilder
         */
        IConfigBuilder useFont(Font font);

        /**
         * fontSize
         *
         * @param size size
         * @return IConfigBuilder
         */
        IConfigBuilder fontSize(int size);

        /**
         * bold
         *
         * @return IConfigBuilder
         */
        IConfigBuilder bold();

        /**
         * toUpperCase
         *
         * @return IConfigBuilder
         */
        IConfigBuilder toUpperCase();

        /**
         * endConfig
         *
         * @return IShapeBuilder
         */
        IShapeBuilder endConfig();
    }

    /**
     * IBuilder Interface
     *
     * @since 2021-05-27
     */
    public interface IBuilder {
        /**
         * build
         *
         * @param text text
         * @param color color
         * @return TextDrawable
         */
        TextDrawable build(String text, int color);
    }

    /**
     * IShapeBuilder Interface
     *
     * @since 2021-05-27
     */
    public interface IShapeBuilder {
        /**
         * beginConfig
         *
         * @return IConfigBuilder
         */
        IConfigBuilder beginConfig();

        /**
         * rect
         *
         * @return IBuilder
         */
        IBuilder rect();

        /**
         * round
         *
         * @return IBuilder
         */
        IBuilder round();

        /**
         * roundRect
         *
         * @param radius radius
         * @return IBuilder
         */
        IBuilder roundRect(int radius);

        /**
         * buildRect
         *
         * @param text text
         * @param color color
         * @return TextDrawable
         */
        TextDrawable buildRect(String text, int color);

        /**
         * buildRoundRect
         *
         * @param text text
         * @param color color
         * @param radius radius
         * @return TextDrawable
         */
        TextDrawable buildRoundRect(String text, int color, int radius);

        /**
         * buildRound
         *
         * @param text text
         * @param color color
         * @return TextDrawable
         */
        TextDrawable buildRound(String text, int color);
    }
}
